home *** CD-ROM | disk | FTP | other *** search
/ Mac Easy 2010 May / Mac Life Ubuntu.iso / casper / filesystem.squashfs / usr / share / system-tools-backends-2.0 / scripts / Utils / Util.pm < prev    next >
Encoding:
Perl POD Document  |  2009-04-09  |  9.7 KB  |  457 lines

  1. #!/usr/bin/perl
  2. #-*- Mode: perl; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
  3.  
  4. # Utility functions.
  5. #
  6. # Copyright (C) 2000-2001 Ximian, Inc.
  7. #
  8. # Authors: Hans Petter Jansson <hpj@ximian.com>
  9. #          Arturo Espinosa <arturo@ximian.com>
  10. #          Michael Vogt <mvo@debian.org> - Debian 2.[2|3] support.
  11. #          David Lee Ludwig <davidl@wpi.edu> - Debian 2.[2|3] support.
  12. #
  13. # This program is free software; you can redistribute it and/or modify
  14. # it under the terms of the GNU Library General Public License as published
  15. # by the Free Software Foundation; either version 2 of the License, or
  16. # (at your option) any later version.
  17. #
  18. # This program is distributed in the hope that it will be useful,
  19. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  20. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  21. # GNU Library General Public License for more details.
  22. #
  23. # You should have received a copy of the GNU Library General Public License
  24. # along with this program; if not, write to the Free Software
  25. # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
  26.  
  27.  
  28. # --- Utilities for strings, arrays and other data structures --- #
  29.  
  30. package Utils::Util;
  31.  
  32. sub max
  33. {
  34.   return ($_[0] > $_[1])? $_[0]: $_[1];
  35. }
  36.  
  37. # Boolean <-> strings conversion.
  38.  
  39. sub read_boolean
  40. {
  41.   my ($v) = @_;
  42.  
  43.   return 1 if ($v =~ "true" ||
  44.                $v =~ "yes"  ||
  45.                $v =~ "YES"  ||
  46.                $v =~ "on"   ||
  47.                $v eq "1");
  48.   return 0;
  49. }
  50.  
  51.  
  52. sub print_boolean_yesno
  53. {
  54.   if ($_[0] == 1) { return "yes"; }
  55.   return "no";
  56. }
  57.  
  58.  
  59. sub print_boolean_truefalse
  60. {
  61.   if ($_[0] == 1) { return "true"; }
  62.   return "false";
  63. }
  64.  
  65.  
  66. sub print_boolean_onoff
  67. {
  68.   if ($_[0] == 1) { return "on"; }
  69.   return "off";
  70. }
  71.  
  72.  
  73. # Pushes a list to an array, only if it's not already in there.
  74. # I'm sure there's a smarter way to do this. Should only be used for small
  75. # lists, as it's O(N^2). Larger lists with unique members should use a hash.
  76.  
  77. sub push_unique
  78. {
  79.   my $arr = $_[0];
  80.   my $found;
  81.   my $i;
  82.  
  83.   # Go through all elements in pushed list.
  84.  
  85.   for ($i = 1; $_[$i]; $i++)
  86.   {
  87.     # Compare against all elements in destination array.
  88.     
  89.     $found = "";
  90.     for $elem (@$arr)
  91.     {
  92.       if ($elem eq $_[$i]) { $found = $elem; last; }
  93.     }
  94.     
  95.     if ($found eq "") { push (@$arr, $_[$i]); }
  96.   }
  97. }
  98.  
  99.  
  100. # Merges scr array into dest array.
  101. sub arr_merge
  102. {
  103.   my ($dest, $src) = @_;
  104.   my (%h, $i);
  105.  
  106.   foreach $i (@$a, @$b)
  107.   {
  108.     $h{$i} = 1;
  109.   }
  110.  
  111.   @$a = keys %h;
  112.   return $a;
  113. }
  114.  
  115. # Given an array and a pattern, it returns the index of the
  116. # array that contains it
  117. sub find_array_index
  118. {
  119.     my($arrayRef, $pattern) = @_;
  120.     my(@array)              = @{$arrayRef};
  121.     my($numElements)        = scalar(@array);
  122.     my(@indexes)            = (0..$numElements);
  123.     my(@elements);
  124.     
  125.     @elements = grep @{$arrayRef}[$_] =~ /$pattern/, @indexes;
  126.     return(wantarray ? @elements : $elements[0]);
  127. }
  128.  
  129.     
  130. sub ignore_line
  131. {
  132.   if (($_[0] =~ /^[ \t]*\#/) || ($_[0] =~ /^[ \t\n\r]*$/)) { return 1; }
  133.   return 0;
  134. }
  135.  
  136.  
  137. # &gst_item_is_in_list
  138. #
  139. # Given:
  140. #   * A scalar value.
  141. #   * An array.
  142. # this function will return 1 if the scalar value is in the array, 0 otherwise.
  143.  
  144. sub item_is_in_list
  145. {
  146.   my ($value, @arr) = @_;
  147.   my ($item);
  148.  
  149.   foreach $item (@arr)
  150.   {
  151.     return 1 if $value eq $item;
  152.   }
  153.  
  154.   return 0;
  155. }
  156.  
  157.  
  158. # Recursively compare a structure made of nested arrays and hashes, diving
  159. # into references, if necessary. Circular references will cause a loop.
  160. # Watch it: arrays must have elements in the same order to be equal.
  161. sub struct_eq
  162. {
  163.   my ($a1, $a2) = @_;
  164.   my ($type1, $type2);
  165.   my (@keys1, @keys2);
  166.   my ($elem1, $elem2);
  167.   my $i;
  168.  
  169.   $type1 = ref $a1;
  170.   $type2 = ref $a2;
  171.   
  172.   return 0 if $type1 != $type2;
  173.   return 1 if $a1 eq $a2;
  174.   return 0 if (!$type1); # Scalars
  175.   
  176.   if ($type1 eq "SCALAR") {
  177.     return 0 if $$a1 ne $$a2;
  178.   }
  179.   elsif ($type1 eq "ARRAY")
  180.   {
  181.     return 0 if $#$a1 != $#$a2;
  182.  
  183.     for ($i = 0; $i <= $#$a1; $i++)
  184.     {
  185.       return 0 if !&struct_eq ($$a1[$i], $$a2[$i]);
  186.     }
  187.   }
  188.   elsif ($type1 eq "HASH") {
  189.     @keys1 = sort keys (%$a1);
  190.     @keys2 = sort keys (%$a2);
  191.  
  192.     return 0 if !&struct_eq (\@keys1, \@keys2);
  193.     foreach $i (@keys1)
  194.     {
  195.       return 0 if !&struct_eq ($$a1{$i}, $$a2{$i});
  196.     }
  197.   }
  198.   else
  199.   {
  200.     return 0;
  201.   }
  202.     
  203.   return 1;
  204. }
  205.  
  206.  
  207. # &gst_get_key_for_subkeys
  208. #
  209. # Given:
  210. #   * A hash-table with its values containing references to other hash-tables,
  211. #     which are called "sub-hash-tables".
  212. #   * A list of possible keys (stored as strings), called the "match_list".
  213. # this method will look through the "sub-keys" (the keys of each
  214. # sub-hash-table) seeing if one of them matches up with an item in the
  215. # match_list.  If so, the key will be returned.
  216.  
  217. sub get_key_for_subkeys
  218. {
  219.   my %hash = %{$_[0]};
  220.   my @match_list = @{$_[1]};
  221.  
  222.   foreach $key (keys (%hash))
  223.   {
  224.     my %subhash = %{$hash{$key}};
  225.     foreach $item (@match_list)
  226.     {
  227.       if ($subhash{$item} ne "") { return $key; }
  228.     }
  229.   }
  230.  
  231.   return "";
  232. }
  233.  
  234.  
  235. # &gst_get_key_for_subkey_and_subvalues
  236. #
  237. # Given:
  238. #   * A hash-table with its values containing references to other hash-tables,
  239. #     which are called "sub-hash-tables".  These sub-hash-tables contain
  240. #     "sub-keys" with associated "sub-values".
  241. #   * A sub-key, called the "match_key".
  242. #   * A list of possible sub-values, called the "match_list".
  243. # this function will look through each sub-hash-table looking for an entry
  244. # whose:
  245. #   * sub-key equals match_key.
  246. #   * sub-key associated sub-value is contained in the match_list.
  247.  
  248. sub get_key_for_subkey_and_subvalues
  249. {
  250.   my %hash = %{$_[0]};
  251.   my $key;
  252.   my $match_key = $_[1];
  253.   my @match_list = @{$_[2]};
  254.  
  255.   foreach $key (keys (%hash))
  256.   {
  257.     my %subhash = %{$hash{$key}};
  258.     my $subvalue = $subhash{$match_key};
  259.  
  260.     if ($subvalue eq "") { next; }
  261.  
  262.     foreach $item (@match_list)
  263.     {
  264.       if ($item eq $subvalue) { return $key; }
  265.     }
  266.   }
  267.  
  268.   return "";
  269. }
  270.  
  271.  
  272. # --- IP calculation --- #
  273.  
  274.  
  275. # ip_calc_network (<IP>, <netmask>)
  276. #
  277. # Calculates the network address and returns it as a string.
  278.  
  279. sub ip_calc_network
  280. {
  281.   my @ip_reg1;
  282.   my @ip_reg2;
  283.  
  284.   @ip_reg1 = ($_[0] =~ /([0-9]+)\.([0-9]+)\.([0-9]+)\.([0-9]+)/);
  285.   @ip_reg2 = ($_[1] =~ /([0-9]+)\.([0-9]+)\.([0-9]+)\.([0-9]+)/);
  286.  
  287.   $ip_reg1[0] = ($ip_reg1[0] * 1) & ($ip_reg2[0] * 1);
  288.   $ip_reg1[1] = ($ip_reg1[1] * 1) & ($ip_reg2[1] * 1);
  289.   $ip_reg1[2] = ($ip_reg1[2] * 1) & ($ip_reg2[2] * 1);
  290.   $ip_reg1[3] = ($ip_reg1[3] * 1) & ($ip_reg2[3] * 1);
  291.  
  292.   return join ('.', @ip_reg1);
  293. }
  294.  
  295.  
  296. # ip_calc_broadcast (<IP>, <netmask>)
  297. #
  298. # Calculates the broadcast address and returns it as a string.
  299.  
  300. sub ip_calc_broadcast
  301. {
  302.   my @ip_reg1;
  303.   my @ip_reg2;
  304.   
  305.   @ip_reg1 = ($_[0] =~ /([0-9]+)\.([0-9]+)\.([0-9]+)\.([0-9]+)/);
  306.   @ip_reg2 = ($_[1] =~ /([0-9]+)\.([0-9]+)\.([0-9]+)\.([0-9]+)/);
  307.  
  308.   @ip_reg1 = ($cf_hostip =~ /([0-9]+)\.([0-9]+)\.([0-9]+)\.([0-9]+)/);
  309.  
  310.   $ip_reg1[0] = ($ip_reg1[0] * 1) | (~($ip_reg2[0] * 1) & 255);
  311.   $ip_reg1[1] = ($ip_reg1[1] * 1) | (~($ip_reg2[1] * 1) & 255);
  312.   $ip_reg1[2] = ($ip_reg1[2] * 1) | (~($ip_reg2[2] * 1) & 255);
  313.   $ip_reg1[3] = ($ip_reg1[3] * 1) | (~($ip_reg2[3] * 1) & 255);
  314.   
  315.   return join ('.', @ip_reg1);
  316. }
  317.  
  318. # Forks a process, running $proc with @args in the child, and
  319. # printing the returned value of $proc in the pipe. Parent
  320. # returns a structure with useful data about the process.
  321. sub process_fork
  322. {
  323.   my ($proc, @args) = @_;
  324.   my $pid;
  325.   local *PARENT_RDR;
  326.   local *CHILD_WTR;
  327.   
  328.   pipe (PARENT_RDR, CHILD_WTR);
  329.   
  330.   $pid = fork ();
  331.   if ($pid)
  332.   {
  333.     # Parent
  334.     close CHILD_WTR;
  335.     return {"pid" => $pid, "fd" => *PARENT_RDR, "fileno" => fileno (*PARENT_RDR)};
  336.   }
  337.   else
  338.   {
  339.     my $ret;
  340.     close PARENT_RDR;
  341.     # Child
  342.     $ret = &$proc (@args);
  343.     my $type = ref ($ret);
  344.  
  345.     if (!$type)
  346.     {
  347.       print CHILD_WTR $ret;
  348.     }
  349.     elsif ($type eq 'ARRAY')
  350.     {
  351.       print CHILD_WTR "$_\n" foreach (@$ret);
  352.     }
  353.  
  354.     close CHILD_WTR;
  355.     exit (0);
  356.   }
  357. }
  358.  
  359.  
  360. # Close pipe, kill process, wait for it to finish.
  361. sub process_kill
  362. {
  363.   my ($proc) = @_;
  364.   
  365.   &Utils::File::close_file ($$proc{"fd"});
  366.   kill 2, $$proc{"pid"};
  367.   waitpid ($$proc{"pid"}, undef);
  368. }
  369.  
  370.  
  371. # Populate a bitmap of the used file descriptors.
  372. sub process_list_build_fd_bitmap
  373. {
  374.   my ($procs) = @_;
  375.   my ($bits, $proc);
  376.   
  377.   foreach $proc (@$procs)
  378.   {
  379.     vec ($bits, $$proc{"fileno"}, 1) = 1;
  380.   }
  381.   
  382.   return $bits;
  383. }
  384.  
  385.  
  386. # Receives a seconds timeout (may be float) and a ref to
  387. # a list of processes (each returned by gst_fork_process), and
  388. # set the "ready" key to true in all the procs that are ready
  389. # to return values, false otherwise. Returns time left before
  390. # timeout.
  391. sub process_list_check_ready
  392. {
  393.   my ($timeout, $procs) = @_;
  394.   my ($bits, $bitsleft, $bitsready, $timestamp, $timeleft);
  395.  
  396.   $procs = [ $procs ] if ref ($procs) ne 'ARRAY';
  397.   $bits = &process_list_build_fd_bitmap ($procs);
  398.   
  399.   # Check with timeout which descriptors are ready with info.
  400.   $timeout = undef if $timeout == 0;
  401.   $timeleft = $timeout;
  402.   $bitsleft = $bits;
  403.   while (($timeout eq undef) || ($timeleft > 0))
  404.   {
  405.     $timestamp = time;
  406.     select ($bitsleft, undef, undef, $timeleft);
  407.     $timeleft -= time - $timestamp if $timeout ne undef;
  408.     
  409.     $bitsready |= $bitsleft;
  410.     $bitsleft = $bits & (~$bitsready);
  411.     last if $bitsready eq $bits;
  412.   }
  413.   $bits = $bitsready;
  414.  
  415.   # For every process, set "ready" key to 1/0 depending on
  416.   # its file descriptor bit.
  417.   foreach $proc (@$procs)
  418.   {
  419.     $$proc{"ready"} = (ord ($bits) & (1 << $$proc{"fileno"}))? 1 : 0;
  420.   }
  421.  
  422.   return $timeleft;
  423. }
  424.  
  425.  
  426. sub process_result_collect
  427. {
  428.   my ($proc, $func, @args) = @_;
  429.   my ($value, $tmp, $lines);
  430.  
  431.   if ($$proc{"ready"})
  432.   {
  433.     my @list;
  434.  
  435.     $lines .= $tmp while (sysread ($$proc{"fd"}, $tmp, 4096));
  436.     goto PROC_KILL unless $lines;
  437.     if ($lines =~ /\n/)
  438.     {
  439.       @list = split ("\n", $lines);
  440.     }
  441.     else
  442.     {
  443.       push @list, $line;
  444.     }
  445.  
  446.     $value = &$func (\@list, @args);
  447.   }
  448.  
  449.  PROC_KILL:
  450.   &process_kill ($proc);
  451.  
  452.   return $value;
  453. }
  454.  
  455.  
  456. 1;
  457.